﻿<%@ Page Language="C#" AutoEventWireup="true" Async="true"%>
<%@ Assembly Name="CrossFactory.SiteNote3_0" %>
<%@ Import Namespace="CrossFactory.SiteNote.Hierarchy" %>
<%@ Import Namespace="CrossFactory.SiteNote.Components" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.IO" %>

<%@ Import Namespace="CrossFactory.SiteNote.Contents" %>
<%@ Import Namespace="Ionic.Zip" %>
<%@ Import Namespace="Ionic.Zlib" %>
<%@ Import Namespace="System.Threading" %>
<script runat="server">
    
    protected override void OnLoad(EventArgs e)
    {
        if (string.IsNullOrEmpty(CrossFactory.SiteNote.Security.SecurityUtil.GetAuthenticatedUser()))
        {
            Response.Clear();
            Response.StatusCode = 401;
            Response.End();
        }
        else
        {
            base.OnLoad(e);
        }
    }

    private delegate string GetArchiveName();
    
    private string CreateContentArchive()
    {
        try
        {
            IHierarchyProvider h = Settings._settings.HierarchyProvider;
            SiteNotePage p = h.GetRootPage(false);
            DirectoryInfo tempDir = new DirectoryInfo(Path.GetTempPath());
            DirectoryInfo contentDir = tempDir.CreateSubdirectory("GetContent-" + Guid.NewGuid().ToString());
            string zipFileName = Path.Combine(contentDir.FullName, "content.zip");
            using (FileStream stream = File.Create(zipFileName))
            {
                using (ZipOutputStream zipOutputStream = new ZipOutputStream(stream))
                {
                    AddPage(contentDir, p, zipOutputStream);
                }

            }
            return zipFileName;

        }
        catch (Exception ex)
        {
            Log.Error("GetContent Error:\n");
            Log.ErrorWithInnerException(ex);
            throw ex;
        }
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(BeginTask, EndTask);
    }

    private void EndTask(IAsyncResult ar)
    {
        Log.Debug("[GetContent] End async: Thread=" + Thread.CurrentThread.ManagedThreadId.ToString());
        GetArchiveName del = (GetArchiveName)ar.AsyncState;
        string zipFileName = del.EndInvoke(ar);
        
        Response.Expires = -1;
        Response.ContentType = "application/force-download";
        Response.AppendHeader("Content-disposition", "attachment; filename=content.zip");
        Response.TransmitFile(zipFileName);
    }

    private IAsyncResult BeginTask(object sender, EventArgs e, AsyncCallback cb, object extradata)
    {
        Log.Debug("[GetContent] Begin async: Thread=" + Thread.CurrentThread.ManagedThreadId.ToString());
        GetArchiveName del = new GetArchiveName(CreateContentArchive);
        return del.BeginInvoke(cb, del);
    }
    
    private void AddPage(DirectoryInfo contentDir, SiteNotePage p, ZipOutputStream stream)
    {
        XmlDocument d = GetPageContent(p);

        stream.CompressionLevel = CompressionLevel.BestCompression;

        string xmlFileName = Path.Combine(contentDir.FullName, p.SiteNotePageInfo.VirtualPath);
        xmlFileName = Path.ChangeExtension(xmlFileName, ".xml");

        ZipEntry entry = stream.PutNextEntry(xmlFileName);
        using (XmlWriter xmlWriter = XmlWriter.Create(stream))
        {
            d.WriteTo(xmlWriter);
        }

        foreach (SiteNotePage page in p.SiteNotePageInfo.subPages)
        {
            AddPage(contentDir, page, stream);
        }
    }

    private XmlDocument GetPageContent(SiteNotePage page)
    {
        StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        StringBuilder xsltLink = new StringBuilder("Global.xslt");
        for (int i = 1; i < page.SiteNotePageInfo.Level; i++ )
        {
            xsltLink.Insert(0, "../");
        }
            xml.AppendLine(string.Format("<?xml-stylesheet type=\"text/xsl\" href=\"{0}\"?>", xsltLink));
        xml.AppendLine(string.Format("<page VirtualPath=\"{0}\" IsHidden=\"{1}\" IsOffline=\"{2}\" level=\"{3}\" name=\"{4}\" template=\"{5}\">", 
            page.SiteNotePageInfo.VirtualPath, page.SiteNotePageInfo.Hidden, page.SiteNotePageInfo.IsOffline, "level_" + page.SiteNotePageInfo.Level, page.SiteNotePageInfo.Name,
            page.SiteNotePageInfo.Template));
        foreach (SiteNoteBlocContent blocContent in page.SiteNotePageInfo.BlocContents.Values)
        {
            GetBlockContentXml(blocContent, ref xml);
        }
        xml.AppendLine("</page>");
        XmlDocument result = new XmlDocument();
        result.LoadXml(xml.ToString());
        return result;
    }

    private void GetBlockContentXml(SiteNoteBlocContent blocContent, ref StringBuilder xml)
    {
        foreach (string key in blocContent.Contents.Keys)
        {
            Control control = blocContent.Contents[key];
            string typeFullName = control.GetType().FullName;
            string xmlEditorTypeName = typeof(CrossFactory.SiteNote.Contents.XmlEditor).FullName;
            string htmlEditorTypeName = typeof(CrossFactory.SiteNote.Contents.HtmlEditor).FullName;
            
            if (typeFullName == xmlEditorTypeName)
            {
                CrossFactory.SiteNote.Contents.XmlEditor editor = (CrossFactory.SiteNote.Contents.XmlEditor)control;
                string contentTypeName = editor.ContentTypeName;
                //xml.AppendLine("<XmlEditor id=\"" + key + "\">");
                xml.AppendLine(string.Format("<{0} id=\"{1}\" BlocId=\"{2}\">", contentTypeName, key, editor.BlocId));
                xml.AppendLine(editor.Xml_String);
                xml.AppendLine(string.Format("</{0}>", contentTypeName));
            } else if (typeFullName == htmlEditorTypeName)
            {
                CrossFactory.SiteNote.Contents.HtmlEditor editor = (CrossFactory.SiteNote.Contents.HtmlEditor)control;
                xml.AppendLine(string.Format("<HtmlEditor id=\"{0}\" BlocId=\"{1}\">", key, editor.BlocId));
                xml.AppendLine(HttpUtility.HtmlEncode(editor.Content));
                xml.AppendLine("</HtmlEditor>");
            }
            else
            {
                CrossFactory.SiteNote.Contents.SiteNoteContent content = control as CrossFactory.SiteNote.Contents.SiteNoteContent;
                    if (content == null)
                    {
                        return;
                    }
                    
                    xml.AppendLine("<" + control.GetType().Name + " id=\"" + key + "\">");
                    xml.AppendLine(HttpUtility.HtmlEncode(content.Content));
                    xml.AppendLine("</" + control.GetType().Name +">");
            }
        }
    }
</script>